/* * Copyright 2010-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://aws.amazon.com/apache2.0 * * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES * OR CONDITIONS OF ANY KIND, either express or implied. See the * License for the specific language governing permissions and * limitations under the License. */ package com.amazonaws.services.s3.internal; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import com.amazonaws.DefaultRequest; import com.amazonaws.Request; import com.amazonaws.SDKGlobalConfiguration; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.BasicAWSCredentials; import com.amazonaws.http.HttpMethodName; import com.amazonaws.services.s3.Headers; import com.amazonaws.services.s3.model.CompleteMultipartUploadRequest; import com.amazonaws.services.s3.model.GetObjectRequest; import com.amazonaws.services.s3.model.HeadBucketRequest; import com.amazonaws.services.s3.model.InitiateMultipartUploadRequest; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.PartETag; import com.amazonaws.services.s3.model.PutObjectRequest; import com.amazonaws.services.s3.model.UploadPartRequest; import com.amazonaws.services.s3.model.transform.RequestXmlFactory; import com.amazonaws.util.StringUtils; import org.junit.After; import org.junit.Before; import org.junit.Test; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URI; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.Date; import java.util.List; public class AWSS3V4SignerTest { @Before public void setup() { System.setProperty(SDKGlobalConfiguration.ENFORCE_S3_SIGV4_SYSTEM_PROPERTY, "true"); } @After public void teardown() { System.clearProperty(SDKGlobalConfiguration.ENFORCE_S3_SIGV4_SYSTEM_PROPERTY); } @Test public void testSignPutObject() throws URISyntaxException { AWSS3V4Signer signer = new S3SignerWithDateOverride(new Date(1431115356859L)); // THESE ARE BOGUS CREDENTIALS AWSCredentials credentials = new BasicAWSCredentials( "AKIAJd4scjDDmxXZTESTGOZQ", "LYd/ad4scjDDmxXZTESTtRz7xdOM1SiD6"); ByteArrayInputStream bais = new ByteArrayInputStream("content".getBytes(StringUtils.UTF8)); ObjectMetadata om = new ObjectMetadata(); om.setContentLength("content".getBytes(StringUtils.UTF8).length); PutObjectRequest por = new PutObjectRequest("test-bucket123456", "key", bais, om); Request<?> pr = new DefaultRequest(por, Constants.S3_SERVICE_NAME); pr.setContent(bais); pr.setResourcePath("key"); pr.setHttpMethod(HttpMethodName.PUT); pr.addHeader(Headers.CONTENT_LENGTH, String.valueOf(bais.available())); pr.setEndpoint(new URI("https://test-bucket123456.s3-us-west-2.amazonaws.com")); pr.addHeader("Host", "test-bucket123456.s3-us-west-2.amazonaws.com"); signer.sign(pr, credentials); assertEquals(getSignature(pr), "e0a8ac165c54dc1fc3dd987f5e00b44f1b91f3c63b05ee642432e1f3c7286d69"); } @Test public void testSignGetObject() throws URISyntaxException { AWSS3V4Signer signer = new S3SignerWithDateOverride(new Date(1431114076667L)); // THESE ARE BOGUS CREDENTIALS AWSCredentials credentials = new BasicAWSCredentials( "AKIAJd4scjDDmxXZTESTGOZQ", "LYd/ad4scjDDmxXZTESTtRz7xdOM1SiD6"); // Simulates getObject GetObjectRequest getRequest = new GetObjectRequest("test-bucket123456", "key"); Request<?> gr = new DefaultRequest(getRequest, Constants.S3_SERVICE_NAME); gr.setEndpoint(new URI("https://test-bucket123456.s3-us-west-2.amazonaws.com")); gr.setHttpMethod(HttpMethodName.GET); gr.setResourcePath("key"); gr.addHeader("Host", "test-bucket123456.s3-us-west-2.amazonaws.com"); signer.sign(gr, credentials); assertEquals(getSignature(gr), "7f8a09e22f7d2899e8b41857516d16ecf10680627c35693958e6e205fda8419e"); } @Test public void testSignMultipartUploads() throws URISyntaxException { AWSS3V4Signer signer = new S3SignerWithDateOverride(new Date(1431114076800L)); // THESE ARE BOGUS CREDENTIALS AWSCredentials credentials = new BasicAWSCredentials( "AKIAJd4scjDDmxXZTESTGOZQ", "LYd/ad4scjDDmxXZTESTtRz7xdOM1SiD6"); // Simulates initiateMultipartUpload InitiateMultipartUploadRequest imur = new InitiateMultipartUploadRequest( "test-bucket123456", "multi-key"); Request<?> ir = new DefaultRequest(imur, Constants.S3_SERVICE_NAME); ir.setEndpoint(new URI("https://test-bucket123456.s3-us-west-2.amazonaws.com")); ir.addHeader("Host", "test-bucket123456.s3-us-west-2.amazonaws.com"); ir.addHeader(Headers.CONTENT_LENGTH, String.valueOf(0)); ir.setResourcePath("multi-key"); ir.addParameter("uploads", null); ir.setContent(new ByteArrayInputStream(new byte[0])); signer.sign(ir, credentials); assertEquals(getSignature(ir), "53ed8e3d923f55ae6f46974083fc6a452467ca3aac755d67a8444866aa0ecfa7"); // Simulates uploadPart ByteArrayInputStream multipartContent = new ByteArrayInputStream( "multipartContent".getBytes(StringUtils.UTF8)); UploadPartRequest upr = new UploadPartRequest(); String uploadId = "6E1pXqay7WGHDsWKZ2vuGlba548bNcLNnwTyTnoxiOFQ6S9hejT_dhBpvA0jLAD04oSLOy6R7hrsFFy00O15MoLYD0heUeOn6SglTE6SKWA-"; upr.withUploadId(uploadId).withPartNumber(1) .withPartSize("multipartContent".getBytes(StringUtils.UTF8).length) .withBucketName("test-bucket123456") .withKey("multi-key") .withInputStream(multipartContent); Request<?> ur = new DefaultRequest(upr, Constants.S3_SERVICE_NAME); ur.addHeader(Headers.CONTENT_LENGTH, String.valueOf("multipartContent".getBytes(StringUtils.UTF8).length)); ur.setEndpoint(new URI("https://test-bucket123456.s3-us-west-2.amazonaws.com")); ur.addHeader("Host", "test-bucket123456.s3-us-west-2.amazonaws.com"); ur.setResourcePath("multi-key"); ur.addParameter("partNumber", "1"); ur.addParameter( "uploadId", "6E1pXqay7WGHDsWKZ2vuGlba548bNcLNnwTyTnoxiOFQ6S9hejT_dhBpvA0jLAD04oSLOy6R7hrsFFy00O15MoLYD0heUeOn6SglTE6SKWA-"); ur.setHttpMethod(HttpMethodName.PUT); signer.sign(ur, credentials); assertEquals(getSignature(ur), "e7c969db60efd061381cea3c16f9906ffa521967fa45a62104b535c89928f68c"); // Simulates completemultipartupload List<PartETag> partETags = new ArrayList<PartETag>(); partETags.add(new PartETag(1, "e6f34498060d371c4f39da1eaadceacb")); CompleteMultipartUploadRequest cmur = new CompleteMultipartUploadRequest( "test-bucket123456", "multi-key", uploadId, partETags); Request<?> cr = new DefaultRequest(cmur, Constants.S3_SERVICE_NAME); cr.setEndpoint(new URI("https://test-bucket123456.s3-us-west-2.amazonaws.com")); cr.addHeader("Host", "test-bucket123456.s3-us-west-2.amazonaws.com"); byte[] xml = RequestXmlFactory.convertToXmlByteArray(partETags); cr.setContent(new ByteArrayInputStream(xml)); cr.addHeader("Content-Length", String.valueOf(xml.length)); cr.addParameter( "uploadId", "6E1pXqay7WGHDsWKZ2vuGlba548bNcLNnwTyTnoxiOFQ6S9hejT_dhBpvA0jLAD04oSLOy6R7hrsFFy00O15MoLYD0heUeOn6SglTE6SKWA-"); cr.setResourcePath("multi-key"); signer.sign(cr, credentials); assertEquals(getSignature(cr), "dc67ca67af0a19b9d70f515879631a287bc8bb18499004420aa294b8beb1b8ec"); } @Test public void testHeadBucket() throws URISyntaxException { AWSS3V4Signer signer = new S3SignerWithDateOverride(new Date(1431114075631L)); // THESE ARE BOGUS CREDENTIALS AWSCredentials credentials = new BasicAWSCredentials( "AKIAJd4scjDDmxXZTESTGOZQ", "LYd/ad4scjDDmxXZTESTtRz7xdOM1SiD6"); // Simulates s3.doesBucketExist Request<?> hr = new DefaultRequest(new HeadBucketRequest("test-bucket123456"), Constants.S3_SERVICE_NAME); hr.setHttpMethod(HttpMethodName.HEAD); hr.setEndpoint(new URI("https://test-bucket123456.s3-us-west-2.amazonaws.com")); hr.addHeader("Host", "test-bucket123456.s3-us-west-2.amazonaws.com"); signer.sign(hr, credentials); assertEquals(getSignature(hr), "fc4922636f1a748e0d2c197b127180c2ae7f5fc1e4a0be33732431f58f6eac51"); } // Gets the Signature from the authorizaiton header private String getSignature(Request<?> request) { String auth = request.getHeaders().get("Authorization"); int index = auth.indexOf("Signature=") + 10; int endIndex = auth.indexOf(" ", index); if (endIndex != -1) { return auth.substring(index, endIndex); } else { return auth.substring(index); } } public void testGetContentLengthMarkNotSupported() throws IOException { Request<?> request = new DefaultRequest<Void>("service"); // Content doesn't support mark request.setContent(new MockInputStream(16, false)); // Should throw exception as mark not supported AWSS3V4Signer.getContentLength(request); } @Test public void testGetContentLength() throws IOException { long len = 5 * Constants.MB; Request<?> request = new DefaultRequest<Void>("service"); InputStream is = new MockInputStream(len, true); request.setContent(is); assertTrue("same length", len == AWSS3V4Signer.getContentLength(request)); assertTrue("works fine after reset", len == AWSS3V4Signer.getContentLength(request)); is.close(); } static class S3SignerWithDateOverride extends AWSS3V4Signer { private S3SignerWithDateOverride(Date overrideDate) { super(); this.overriddenDate = overrideDate; } } /** * A simple input stream class that allows you to specify the content length * as well as whether it supports mark. */ static class MockInputStream extends InputStream { private final long len; private final boolean markSupported; private long count; public MockInputStream(long len, boolean markSupported) { this.len = len; this.markSupported = markSupported; } @Override public int read() throws IOException { count++; return count <= len ? (int) (count & 0xff) : -1; } @Override public boolean markSupported() { return markSupported; } @Override public synchronized void reset() throws IOException { if (markSupported) { count = 0; } else { super.reset(); } } } }